home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procFamily.c < prev    next >
C/C++ Source or Header  |  1990-09-12  |  11KB  |  429 lines

  1. /*
  2.  *  procFamily.c --
  3.  *
  4.  *    Routines to manage process families.  Families are implemented using
  5.  *    a hash table each entry of which points to a process family list.
  6.  *    This hash table and process families in general are managed by a 
  7.  *    monitor lock.
  8.  *
  9.  *    The only field in the proc table managed by routines in this monitor
  10.  *    is the familyID field.
  11.  *
  12.  * Copyright (C) 1986 Regents of the University of California
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procFamily.c,v 9.1 90/09/12 13:58:09 jhh Exp $ SPRITE (Berkeley)";
  24. #endif /* not lint */
  25.  
  26. #include <sprite.h>
  27. #include <proc.h>
  28. #include <stdlib.h>
  29. #include <status.h>
  30. #include <sync.h>
  31. #include <sched.h>
  32. #include <hash.h>
  33.  
  34. static    Sync_Lock    familyLock;
  35. #define    LOCKPTR &familyLock
  36. Sync_Condition    familyCondition;
  37.  
  38. static Hash_Table    famHashTableStruct;
  39. static Hash_Table    *famHashTable = &famHashTableStruct;
  40.  
  41. #define    FAMILY_HASH_SIZE    8
  42.  
  43. /*
  44.  * A family list header.
  45.  */
  46.  
  47. typedef struct {
  48.     List_Links        famList;    /* Pointer to family list. */
  49.     Boolean        locked;        /* TRUE => family locked. */
  50.     Sync_Condition    condition;    /* Condition to wait on when family
  51.                      * locked. */
  52.     int            userID;        /* Effective userid of process that
  53.                      * created the family. */
  54. } FamilyHeader;
  55.  
  56.  
  57. /*
  58.  *----------------------------------------------------------------------
  59.  *
  60.  * ProcFamilyHashInit --
  61.  *
  62.  *    Initialize the family id hash table and the family lock.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    Family id hash table initialized.
  69.  *
  70.  *----------------------------------------------------------------------
  71.  */
  72.  
  73. void
  74. ProcFamilyHashInit()
  75. {
  76.     Sync_LockInitDynamic(&familyLock, "Proc:familyLock");
  77.     Hash_Init(famHashTable, FAMILY_HASH_SIZE, Hash_Size(sizeof(int)));
  78. }
  79.  
  80.  
  81. /*
  82.  *----------------------------------------------------------------------
  83.  *
  84.  * ProcFamilyInsert --
  85.  *
  86.  *    Insert the process into the given family.
  87.  *
  88.  * Results:
  89.  *    PROC_UID_MISMATCH if effective userid of process does not match
  90.  *    userid of family.  SUCCESS otherwise.
  91.  *
  92.  * Side effects:
  93.  *    Process inserted into family list.  If family doesn't exist then
  94.  *    the family is created with the userid of the given process.
  95.  *
  96.  *----------------------------------------------------------------------
  97.  */
  98.  
  99. ENTRY ReturnStatus
  100. ProcFamilyInsert(procPtr, familyID)
  101.     Proc_ControlBlock    *procPtr;
  102.     int            familyID;
  103. {
  104.     register    Hash_Entry    *hashEntryPtr;
  105.     register    FamilyHeader    *famHdrPtr;
  106.  
  107.     LOCK_MONITOR;
  108.  
  109.     if (familyID == PROC_NO_FAMILY) {
  110.     UNLOCK_MONITOR;
  111.     return(SUCCESS);
  112.     }
  113.  
  114. again:
  115.     hashEntryPtr = Hash_Find(famHashTable, (Address) familyID);
  116.     famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
  117.     if (famHdrPtr == (FamilyHeader *) NIL) {
  118.     famHdrPtr = (FamilyHeader *) malloc(sizeof(FamilyHeader));
  119.     List_Init(&famHdrPtr->famList);
  120.     Hash_SetValue(hashEntryPtr, famHdrPtr);
  121.     famHdrPtr->locked = FALSE;
  122.     famHdrPtr->userID = procPtr->effectiveUserID;
  123.     } else {
  124.     if (famHdrPtr->locked) {
  125.         (void) Sync_Wait(&famHdrPtr->condition, FALSE);
  126.         goto again;
  127.     }
  128. #ifdef CHECK_PROT
  129.     if (famHdrPtr->userID != procPtr->effectiveUserID &&
  130.             procPtr->effectiveUserID != PROC_SUPER_USER_ID) {
  131.         printf("Uid-mismatch: pid %x puid %d fid %x fuid %d\n",
  132.             procPtr->processID, procPtr->effectiveUserID,
  133.             familyID, famHdrPtr->userID);
  134.         UNLOCK_MONITOR;
  135.         return(PROC_UID_MISMATCH);
  136.     }
  137. #endif /* */
  138.     }
  139.     List_Insert((List_Links *) &(procPtr->familyElement), 
  140.         LIST_ATFRONT(&famHdrPtr->famList));
  141.  
  142.     UNLOCK_MONITOR;
  143.     return(SUCCESS);
  144. }
  145.  
  146.  
  147. /*
  148.  *----------------------------------------------------------------------
  149.  *
  150.  * ProcFamilyRemove --
  151.  *
  152.  *    Remove the process from the given family list.
  153.  *
  154.  * Results:
  155.  *    None.
  156.  *
  157.  * Side effects:
  158.  *    Process removed from its family list.  If process isn't in a family
  159.  *    then nothing happens.
  160.  *
  161.  *----------------------------------------------------------------------
  162.  */
  163.  
  164. ENTRY void
  165. ProcFamilyRemove(procPtr)
  166.     Proc_ControlBlock    *procPtr;
  167. {
  168.     register    Hash_Entry    *hashEntryPtr;
  169.     register    FamilyHeader    *famHdrPtr;
  170.  
  171.     LOCK_MONITOR;
  172.  
  173.     if (procPtr->familyID == PROC_NO_FAMILY) {
  174.     UNLOCK_MONITOR;
  175.     return;
  176.     }
  177.  
  178.     hashEntryPtr = Hash_LookOnly(famHashTable, (Address) procPtr->familyID);
  179.     if (hashEntryPtr == (Hash_Entry *) NIL) {
  180.     panic("ProcFamilyRemove: Family not in hash table\n");
  181.     }
  182.     famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
  183.     while (famHdrPtr->locked) {
  184.     (void) Sync_Wait(&famHdrPtr->condition, FALSE);
  185.     }
  186.  
  187.     List_Remove((List_Links *) &(procPtr->familyElement));
  188.     if (List_IsEmpty(&famHdrPtr->famList)) {
  189.     free((Address) famHdrPtr);
  190.     Hash_Delete(famHashTable, hashEntryPtr);
  191.     }
  192.  
  193.     UNLOCK_MONITOR;
  194. }
  195.  
  196.  
  197. /*
  198.  *----------------------------------------------------------------------
  199.  *
  200.  * Proc_LockFamily --
  201.  *
  202.  *    Prevent the given family from being modified.
  203.  *
  204.  * Results:
  205.  *    PROC_INVALID_FAMILYID     - The pid argument was illegal.
  206.  *    PROC_UID_MISMATCH    - The callers uid doesn't match the uid of the
  207.  *                  family.
  208.  *
  209.  * Side effects:
  210.  *    Process family lock flag set.
  211.  *
  212.  *----------------------------------------------------------------------
  213.  */
  214.  
  215. ENTRY ReturnStatus
  216. Proc_LockFamily(familyID, familyListPtr, userIDPtr)
  217.     int        familyID;        /* Family to lock. */
  218.     List_Links    **familyListPtr;    /* Where to return pointer to family
  219.                      * list. */
  220.     int        *userIDPtr;        /* Place to return the user id of the
  221.                      * family. */
  222. {
  223.     register    Hash_Entry    *hashEntryPtr;
  224.     register    FamilyHeader    *famHdrPtr;
  225.  
  226.     LOCK_MONITOR;
  227.  
  228. again:
  229.     hashEntryPtr = Hash_LookOnly(famHashTable, (Address) familyID);
  230.     if (hashEntryPtr == (Hash_Entry *) NIL) {
  231.     UNLOCK_MONITOR;
  232.     return(PROC_INVALID_FAMILY_ID);
  233.     }
  234.     famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
  235.  
  236.     if (famHdrPtr->locked) {
  237.     /*
  238.      * The family is locked so wait for it to become unlocked.  When
  239.      * wake up start over because the family could have been deleted while
  240.      * we were sleeping.
  241.      */
  242.     (void) Sync_Wait(&famHdrPtr->condition, FALSE);
  243.     goto again;
  244.     }
  245.     famHdrPtr->locked = TRUE;
  246.     *familyListPtr = &(famHdrPtr->famList);
  247.     *userIDPtr = famHdrPtr->userID;
  248.  
  249.     UNLOCK_MONITOR;
  250.  
  251.     return(SUCCESS);
  252. }
  253.  
  254.  
  255. /*
  256.  *----------------------------------------------------------------------
  257.  *
  258.  * Proc_UnlockFamily --
  259.  *
  260.  *    Allow the family to be modified.
  261.  *
  262.  * Results:
  263.  *    None.
  264.  *
  265.  * Side effects:
  266.  *    Family id header element lock bit cleared.
  267.  *
  268.  *----------------------------------------------------------------------
  269.  */
  270.  
  271. ENTRY void
  272. Proc_UnlockFamily(familyID)
  273.     int    familyID;
  274. {
  275.     register    Hash_Entry    *hashEntryPtr;
  276.     register    FamilyHeader    *famHdrPtr;
  277.  
  278.     LOCK_MONITOR;
  279.  
  280.     hashEntryPtr = Hash_LookOnly(famHashTable, (Address) familyID);
  281.     if (hashEntryPtr == (Hash_Entry *) NIL) {
  282.     panic("Proc_UnlockFamily: Family doesn't exist\n");
  283.     }
  284.     famHdrPtr = (FamilyHeader *) Hash_GetValue(hashEntryPtr);
  285.  
  286.     if (!famHdrPtr->locked) {
  287.     panic("Proc_UnlockFamily: Family isn't locked\n");
  288.     }
  289.  
  290.     famHdrPtr->locked = FALSE;
  291.     Sync_Broadcast(&famHdrPtr->condition);
  292.  
  293.     UNLOCK_MONITOR;
  294. }
  295.  
  296.  
  297. /*
  298.  *----------------------------------------------------------------------
  299.  *
  300.  * Proc_GetFamilyID --
  301.  *
  302.  *    Returns the ID of the head of the process family
  303.  *    for the given process.
  304.  *
  305.  * Results:
  306.  *    SYS_ARG_NOACCESS -     the argument was not accessible.
  307.  *    SYS_INVALID_ARG -     the argument was was invalid.
  308.  *    PROC_INVALID_PID -    the pid argument was illegal.
  309.  *    PROC_UID_MISMATCH -    the calling process does not have permission
  310.  *                to read the given process's family id.
  311.  *
  312.  * Side effects:
  313.  *    None.
  314.  *
  315.  *----------------------------------------------------------------------
  316.  */
  317. ReturnStatus
  318. Proc_GetFamilyID(pid, familyIDPtr)
  319.     Proc_PID    pid;
  320.     Proc_PID    *familyIDPtr;
  321. {
  322.     register    Proc_ControlBlock     *procPtr;
  323.     Proc_PID                familyID;
  324.  
  325.     if (familyIDPtr == USER_NIL) {
  326.     return(SYS_INVALID_ARG);
  327.     } 
  328.  
  329.     if (pid == PROC_MY_PID) {
  330.     procPtr = Proc_GetEffectiveProc();
  331.     Proc_Lock(procPtr);
  332.     } else {
  333.     /*
  334.      *   Get the PCB entry for the given process.
  335.      */
  336.     procPtr = Proc_LockPID(pid);
  337.     if (procPtr == (Proc_ControlBlock *) NIL) {
  338.         return(PROC_INVALID_PID);
  339.     }
  340.     if (!Proc_HasPermission(procPtr->effectiveUserID)) {
  341.         Proc_Unlock(procPtr);
  342.         return(PROC_UID_MISMATCH);
  343.     }
  344.     }
  345.  
  346.     familyID = procPtr->familyID;
  347.     Proc_Unlock(procPtr);
  348.     if (Proc_ByteCopy(FALSE, sizeof(Proc_PID), (Address) &familyID, 
  349.               (Address) familyIDPtr) != SUCCESS){
  350.     return(SYS_ARG_NOACCESS);
  351.     }
  352.     return(SUCCESS);
  353. }
  354.  
  355.  
  356. /*
  357.  *----------------------------------------------------------------------
  358.  *
  359.  * Proc_SetFamilyID --
  360.  *
  361.  *    Changes the family ID of a process to the one specified.
  362.  *
  363.  *
  364.  * Results:
  365.  *    PROC_UID_MISMATCH -     The current process did not have the same
  366.  *                uid as the family or the calling process
  367.  *                does not have permission to set the given
  368.  *                process's family id.
  369.  *    PROC_INVALID_FAMILY_ID  The given family ID is not a valid process ID.
  370.  *
  371.  * Side effects:
  372.  *    Changes the family ID field in the Proc_ControlBlock for a process.
  373.  *
  374.  *----------------------------------------------------------------------
  375.  */
  376.  
  377. ReturnStatus
  378. Proc_SetFamilyID(pid, familyID)
  379.     Proc_PID    pid;
  380.     Proc_PID    familyID;
  381. {
  382.     register Proc_ControlBlock    *procPtr;
  383.     Proc_ControlBlock        *famProcPtr;
  384.     ReturnStatus        status;
  385.  
  386.     /*
  387.      * Make sure that the familyID is a valid process ID.  This is necessary
  388.      * to let process group signals to be sent across machines.
  389.      */
  390.     famProcPtr = Proc_LockPID(familyID);
  391.     if (famProcPtr == (Proc_ControlBlock *) NIL) {
  392.     return(PROC_INVALID_FAMILY_ID);
  393.     }
  394.     Proc_Unlock(famProcPtr);
  395.  
  396.     if (pid == PROC_MY_PID) {
  397.     procPtr = Proc_GetEffectiveProc();
  398.     Proc_Lock(procPtr);
  399.     } else {
  400.     /*
  401.      *   Get the PCB entry for the given process.
  402.      */
  403.     procPtr = Proc_LockPID(pid);
  404.     if (procPtr == (Proc_ControlBlock *) NIL) {
  405.         return(PROC_INVALID_PID);
  406.     }
  407.     if (!Proc_HasPermission(procPtr->effectiveUserID)) {
  408.         Proc_Unlock(procPtr);
  409.         return(PROC_UID_MISMATCH);
  410.     }
  411.     }
  412.  
  413.     ProcFamilyRemove(procPtr);
  414.     status = ProcFamilyInsert(procPtr, (int) familyID);
  415.     if (status == SUCCESS) {
  416.     procPtr->familyID = familyID;
  417.     } else {
  418.     procPtr->familyID = PROC_NO_FAMILY;
  419.     }
  420.  
  421.     if (procPtr->state == PROC_MIGRATED) {
  422.     status = Proc_MigUpdateInfo(procPtr);
  423.     }
  424.  
  425.     Proc_Unlock(procPtr);
  426.  
  427.     return(status);
  428. }
  429.